package template

import (
	"io"

	"gitee.com/lipore/plume/db_gorm/dal/models"
)

type ModelMapping struct {
	EntityName string
	ModelName  string
	Fields     []FieldMapping
}

type FieldMapping struct {
	ModelName  string
	EntityName string
}

const Entity2Model = `
func (e *{{.EntityName}}) ToModel() *{{.ModelName}} {
	return &{{.ModelName}}{
		{{- range .Fields}}
		{{.ModelName}}: e.{{.EntityName}},
		{{- end }}
	}
}
`

const Model2Entity = `
func (e *{{.EntityName}}) FromModel(m *{{.ModelName}}) *{{.EntityName}} {
	{{range .Fields}}e.{{.EntityName}} = m.{{.ModelName}}
	{{ end -}}
	return e
}
`

func GenerateToModel(w io.Writer, mapping interface{}) {
	err := render(Entity2Model, w, mapping)
	if err != nil {
		panic(err)
	}
}
func GenerateFromModel(w io.Writer, mapping interface{}) {
	err := render(Model2Entity, w, mapping)
	if err != nil {
		panic(err)
	}
}

type NotImplementData struct {
	EntityName string
	Method     *models.MethodInfo
}

const NotImplement = `
func ({{.EntityName}}) {{.Method.Name}}({{- range .Method.Params}}{{.Name}} {{.Type}},{{- end}}) ({{- range .Method.Results}}{{.Type}},{{- end}}) {
	panic("implement me")
}
`

func GenerateNotImplement(w io.Writer, data interface{}) {
	err := render(NotImplement, w, data)
	if err != nil {
		panic(err)
	}
}

type GetSetData struct {
	EntityName string
	FieldName  string
	FieldType  string
}

const Get = `
func (e *{{.EntityName}}) Get{{.FieldName}}() {{.FieldType}} {
	return e.{{.FieldName}}
}
`

func GenerateGet(w io.Writer, data interface{}) {
	err := render(Get, w, data)
	if err != nil {
		panic(err)
	}
}

const Set = `
func (e *{{.EntityName}}) Set{{.FieldName}}({{.FieldName}} {{.FieldType}}) {
	e.{{.FieldName}} = {{.FieldName}}
}
`

func GenerateSet(w io.Writer, data interface{}) {
	err := render(Set, w, data)
	if err != nil {
		panic(err)
	}
}

type BaseCrudData struct {
	EntityName string
	IdFields   []*models.FieldInfo
}

const Create = `
func (e *{{.EntityName}}) Create(ctx context.Context) error {
	return db_gorm.WithTx(ctx, func(tx *gorm.DB) error {
		return tx.Create(e).Error
	})
}`

func GenerateCreate(w io.Writer, data interface{}) {
	err := render(Create, w, data)
	if err != nil {
		panic(err)
	}
}

const Find = `
func (e *{{.EntityName}}) Find(ctx context.Context) error {
	return db_gorm.WithTx(ctx, func(tx *gorm.DB) error {
		return tx.First(e).Error
	})
}`

func GenerateFind(w io.Writer, data interface{}) {
	err := render(Find, w, data)
	if err != nil {
		panic(err)
	}
}

const Update = `
func (e *{{.EntityName}}) Update(ctx context.Context) error {
	return db_gorm.WithTx(ctx, func(tx *gorm.DB) error {
		return tx.Save(e).Error
	})
}`

func GenerateUpdate(w io.Writer, data interface{}) {
	err := render(Update, w, data)
	if err != nil {
		panic(err)
	}
}

const Delete = `
func (e *{{.EntityName}}) Delete(ctx context.Context) error {
	return db_gorm.WithTx(ctx, func(tx *gorm.DB) error {
		return tx.Delete(e).Error
	})
}`

func GenerateDelete(w io.Writer, data interface{}) {
	err := render(Delete, w, data)
	if err != nil {
		panic(err)
	}
}

type ByFieldData struct {
	ColumnName string
	Param      *models.FieldInfo
}

type DiyFindData struct {
	BaseCrudData
	Fields []*ByFieldData
}

const DiyFind = `
func (e *{{.EntityName}}) Find(ctx context.Context) error {
	return db_gorm.WithTx(ctx, func(tx *gorm.DB) error {
		return tx
		{{- if .Fields}}{{- range .Fields}}.Where("{{.ColumnName}} = ?", e.{{.Param.Name}}){{- end}}{{- end}}
		.First(e).Error
	})
}`

type EntityCreatorData struct {
	ModelName      string
	ModelInterface string
	ModelPkgName   string
	EntityName     string
}

const EntityCreator = `
func {{.ModelName}}Creator() {{.ModelInterface}} {
	return &{{.EntityName}}{}
}

func init() {
	{{.ModelPkgName}}.Setup{{.ModelName}}Creator({{.ModelName}}Creator)
}
`

func GenerateEntityCreator(w io.Writer, data interface{}) {
	err := render(EntityCreator, w, data)
	if err != nil {
		panic(err)
	}
}
